package com.ceprei.gui.service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ceprei.domain.common.BaseEntity;
import org.apache.commons.collections4.CollectionUtils;

import java.io.Serializable;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * @author zhou minghao
 * @date 2024/11/29
 * @description
 */
public interface BasicService <T extends BaseEntity> extends IService<T> {
    /**
     * 根据对象查询数据是否存在
     *
     * @param t 实体类
     * @return 是否存在满足条件的数据
     */
    default boolean exists(T t) {
        return this.count(t) > 0;
    }

    /**
     * 根据对象查询数据是否存在
     *
     * @param list
     * @return
     */
    default boolean exists(List<T> list) {
        for (T t : list) {
            if (this.count(t) > 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * 自动将实体类参数对象包装为 {@link QueryWrapper <T>} 的 {@link #list(Wrapper)} 查询
     *
     * @param t 实体类
     * @return 查询到的数据列表
     */
    default List<T> list(T t) {
        return this.list(new QueryWrapper<>(t));
    }

    /**
     * listObjs的包装
     *
     * @param t
     * @return
     */
    default List<Object> objs(T t) {
        return this.listObjs(new QueryWrapper<>(t));
    }

    /**
     * 自动将实体类参数对象包装为 {@link QueryWrapper<T>} 的 {@link #getOne(Wrapper)}} 查询
     *
     * @param t 实体类
     * @return 查询到的数据
     */
    default T one(T t) {
        return getOne(new QueryWrapper<>(t));
    }

    /**
     * 自动将实体类参数对象包装为 {@link QueryWrapper<T>} 的 {@link #count(Wrapper)} 查询
     *
     * @param t 实体类
     * @return 查询到的数据
     */
    default int count(T t) {
        return count(new QueryWrapper<>(t));
    }

    /**
     * 查询第一个符合条件的对象
     *
     * @param t 实体类
     * @return 查询到的数据
     */
    default T first(T t) {
        return first(new QueryWrapper<>(t));
    }

    /**
     * 查询第一个符合条件自定义返回值的对象，
     *
     * @param t
     * @param column
     * @return
     */
    default T firstReturnColumn(T t, String... column) {
        return first(new QueryWrapper<>(t).select(column));
    }

    /**
     * 查询第一个符合条件自定义返回值的对象，
     * *
     *
     * @param t
     * @param columns
     * @return
     */
    default T firstReturnColumn(T t, SFunction<T, ?>... columns) {
        List<T> list = list(Wrappers.lambdaQuery(t).select(columns).last("limit 1"));
        return CollectionUtils.isEmpty(list) ? null : list.get(0);
    }

    /**
     * 查询第一个符合条件的对象
     *
     * @param wrapper 包装实体类
     * @return 查询到的数据
     */
    default T first(QueryWrapper<T> wrapper) {
        final List<T> list = this.list(wrapper.last("limit 1"));
        return CollectionUtils.isEmpty(list) ? null : list.get(0);
    }

    /**
     * 自动将实体类参数对象包装为 {@link QueryWrapper<T>} 的 {@link #page(Page, BaseEntity)} 查询
     *
     * @param page
     * @param t
     * @return
     */
    default Page<T> page(Page<T> page, T t) {
        return page(page, new QueryWrapper<>(t));
    }

    /**
     * 自动将实体类参数对象包装为 {@link Wrappers<T>} 的 {@link #remove(Wrapper)} 查询
     *
     * @param t 实体类
     * @return 删除结果
     */
    default boolean remove(T t) {
        return remove(Wrappers.query(t));
    }

    /**
     * 根据实体类列表批量查询实体类列表
     *
     * @param list 实体类列表
     * @return 查询到的实体类列表（自动去重）
     */
    List<T> listBatchByEntityList(List<T> list);


    /**
     * 忽略删除状态的修改
     *
     * @param t 条件对象
     * @return 是否修改成功
     */
    boolean updateIgnoreDelFlag(T t);

    /**
     * 批量忽略删除状态的修改
     *
     * @param t 条件对象集合
     * @return 是否修改成功
     */
    boolean updateBatchIgnoreDelFlag(List<T> t);

    /**
     * 批量插入 用values(),(),(),()...的方式插入提交效率
     *
     * @param t 要插入的数据
     * @return
     */
    boolean insertBatchByMysql(List<T> t);

    /**
     * 批量插入 用values(),(),(),()...的方式插入提交效率
     *
     * @param t   要插入的数据
     * @param num 每次插入的数据量
     * @return
     */
    boolean insertBatchByMysql(List<T> t, int num);

    /**
     * Vo分页查询
     *
     * @param page
     * @param entity
     * @param <Vo>
     * @return-
     */
    <Vo extends T> Page<Vo> queryPageVo(Page<Vo> page, Vo entity);

    /**
     * Vo的列表查询,默认行为是list<T>()的结果包装成 List<Vo extends T>(),需要自定义请实现BasicMapper.listVo()
     *
     * @param vo vo实例
     * @param <Vo> Vo
     */
    <Vo extends T> List<Vo> listVo(Vo vo);

    /**
     * tree结构返回
     *
     * @param getVo       vo
     * @param treeRootId  树根节点ID
     * @param getParentId 获取父节点ID
     * @param getId       获取ID函数
     * @param setChildren 设置Children函数
     * @param <Vo>        vo对象
     * @param <R>         ID 实现Serializable 一般是int
     * @return 整颗树
     */
    <Vo extends T, R extends Serializable> List<Vo> buildTree(Supplier<Vo> getVo, R treeRootId, Function<Vo, R> getParentId, Function<Vo, R> getId, BiConsumer<Vo, List<Vo>> setChildren);

    /**
     * tree结构返回,注意treeRootId,getParentId和getId返回的类型必须相同
     *
     * @param voList      voList
     * @param treeRootId  树根节点ID
     * @param getParentId 获取父节点ID
     * @param getId       获取ID函数
     * @param setChildren 设置Children函数
     * @param <Vo>        vo对象
     * @param <R>         ID 实现Serializable 一般是int
     * @return 整颗树
     */
    <Vo extends T, R> List<Vo> buildTree(List<Vo> voList, R treeRootId, Function<Vo, R> getParentId, Function<Vo, R> getId, BiConsumer<Vo, List<Vo>> setChildren);

    <Vo extends T, R> List<Vo> buildTree(List<Vo> voList, R treeRootId, Function<Vo, R> getParentId, Function<Vo, R> getId, BiConsumer<Vo, List<Vo>> setChildren, Predicate<Vo> parentFilter);

}
